package com.lz.boot;
/**
 * App..
 * 基于以下两种注解，Test测试
 * @RunWith(SpringJUnit4ClassRunner.class)
 * @ContextConfiguration(locations = {"classpath:applicationContext.xml"})
 *
 * @author Lizhong
 * @date 2019/5/7
 */

import com.lz.core.beans.Bean01;
import com.lz.core.beans.Bean04BeanNameAware;
import com.lz.core.beans.Bean07;
import com.lz.core.beans.Lesson;
import com.lz.core.beans.Student;
import com.lz.core.beans.constructor.ConstructorIndex;
import com.lz.core.beans.lookup.Bean06Parent;
import com.lz.core.beans.lookup.GetBean06;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import javax.annotation.Resource;
import java.util.Arrays;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
public class App {
    @Autowired
    Student student;
    @Autowired
    Lesson lesson;

    @Test
    public void test() {
        System.out.println("student:\r" + student);
        System.out.println("lesson:\r" + lesson);


    }

    @Autowired
    Bean01 bean01;

    @Test
    public void constructor() {
        System.out.println(bean01);
    }

    /**
     * 几个不同装配
     */
    // @Resource(name = "lesson03")
    // @Named("lesson03") null
/*    @Inject
    @Named("lesson03")*/
    // @Resource(name = "lesson03")
          /* @Autowired
            @Named("lesson02")*/
    // @Qualifier("lesson02") null
/*            @Inject
            @Qualifier("lesson02")*/
// @Inject
    //  @Autowired
    @Resource(name = "lesson02")
    Lesson lesson002;

    @Test
    public void resource() {
        System.out.println(lesson002);
    }
    /*
    Spring 框架中注解
    @Autowired  ：默认是按照byType进行注入的，如果发现找到多个bean byName方式比对
    @Qualifier ：组合指定name后byName

    javax.annotation:
    @Resource   先byName后byType
    @Qualifier   风spring

    javaee注解:
    @Inject    默认是按照byType进行注入的，如果发现找到多个bean byName方式比对
    @Named      组合后指定name  byName

    @Inject=@autowire(true)，后者多了个false ，@Name=@Qualifier ，
    @Resource
        1. 如果同时指定了name和type，则从Spring上下文中找到唯一匹配的bean进行装配，找不到则抛出异常
        2. 如果指定了name，则从上下文中查找名称（id）匹配的bean进行装配，找不到则抛出异常
        3. 如果指定了type，则从上下文中找到类型匹配的唯一bean进行装配，找不到或者找到多个，都会抛出异常
        4. 如果既没有指定name，又没有指定type，则自动按照byName方式进行装配；如果没有匹配，则回退为一个原始类型进行匹配，如果匹配则自动装配
    */

    /**
     * 测试BeanNameAware ，可以将<Bean id></Bean>,可以将标签中的id 通过BeanNameAware#serBeanName 取出通过该该方法赋值
     */
    @Autowired
    // @Qualifier("bean01")
            Bean01 beanNoAware;
    @Autowired
    Bean04BeanNameAware bean04BeanNameAware;

    @Test
    public void beanNameAwareTest() {
        System.out.println(beanNoAware);
        System.out.println(bean04BeanNameAware);
    }

    /**
     *  注解@primary Test，根据byType 时多个bean
     *  可以指定Primary
     */
    @Autowired
    Lesson beansds;

    @Test
    public void primaryTest() {
        Assert.assertEquals(beansds.getName(), "语文");
    }

    /**
     * look-up method ,replace-method Test
     */
    @Autowired
    GetBean06 getBean06;

    @Test
    public void methodTest() {
        // 指定Bean061
        Bean06Parent bean06 = getBean06.getBean06();
        // replace-method are invoked;
        getBean06.changedMethod();
    }

    @Autowired
    ConstructorIndex constructorIndex;

    @Test
    public void constructorIndexTest() {
        System.out.println(constructorIndex);
    }

    @Resource
    ApplicationContext applicationContext;

    @Test
    public void allGenerator() {
        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
        System.out.println(Arrays.toString(beanDefinitionNames));
        Object lesson = applicationContext.getBean("student");
    }

    /**
     * 模拟FactoryBean未完全初始化调用getObject，抛异常失败
     */
    @Test
    public void factoryBean() {
        Object lesson = applicationContext.getBean("myFactoryBean");
        System.out.println(lesson);
    }
    @Test
    public void nestedTest(){
        Bean07 bean =(Bean07) applicationContext.getBean("bean07");
        System.out.println(bean);
        Assert.assertEquals(".Chinese",bean.getStudent().getLesson().getName());
    }
}
